package com.ijecorp.media.riff;

import java.io.DataInputStream;
import java.io.IOException;

import com.ijecorp.media.fmt.WaveFormat;

//http://www.sonicspot.com/guide/wavefiles.html#fact
public class RIFFChunkReader {
	public static RIFFChunk readChunk(DataInputStream in){
		try {
			final int chunkID = in.readInt();
			switch(chunkID){
			case RIFFChunk.RIFF_ID:
				return readRIFFChunk(chunkID, in);		
			}


		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;		
	}

	private static RIFFChunk readRIFFChunk(final int chunkID, DataInputStream in) throws IOException{
		final int chunkSize = Integer.reverseBytes(in.readInt()) ;		
		return new RIFFChunk(chunkID, chunkSize);
	}

	public static WAVEChunk readWaveChunk(DataInputStream in) throws IOException{
		final int chunkID = in.readInt();
		if(chunkID != RIFFChunk.RIFF_ID ){
			throw new RuntimeException("It is not RIFF format");
		}
		final int chunkSize = Integer.reverseBytes(in.readInt()) ;			

		//: WAVE Chunk
		final int waveID = in.readInt() ;			
		if(waveID!=WaveFormat.TYPE_ID){
			throw new RuntimeException("It is not WAVE format "+ waveID);				
		}		
		final WAVEChunk waveChunk = new WAVEChunk(chunkID, chunkSize, waveID);


		while(in.available() > 0){
			final int subChunkID = in.readInt();
			switch(subChunkID){
			case WaveFmtChunk.FMT_ID:
				waveChunk.addSubChunk(readFormatChunk(in));
				break;
			case WaveFactChunk.FACT_ID:
				waveChunk.addSubChunk(readFactChunk(in));
				break;
			case WaveCueChunk.CUE_ID:
				break;
			case WaveDataChunk.DATA_ID:
				waveChunk.addSubChunk(readDataChunk(in));
				break;
			default:
				throw new RuntimeException("Not support subChunkID = " + subChunkID);
			}
//			waveChunk.addSubChunk(chunk)
		}


		return waveChunk;
	}


	private static WaveDataChunk readDataChunk(DataInputStream in) throws IOException{
		final int chunkSize = Integer.reverseBytes(in.readInt()) ;		
		final byte[] sampleData = new byte[chunkSize];
		in.read( sampleData);		
		return new WaveDataChunk(sampleData);	
	}

	private final static WaveFmtChunk readFormatChunk(DataInputStream in) throws IOException {
		final int chunkSize = Integer.reverseBytes(in.readInt()) ;			
		final WaveFmtChunk chunk = new WaveFmtChunk(WaveFmtChunk.FMT_ID, chunkSize );
		chunk.code = Short.reverseBytes(in.readShort());
		chunk.channels = Short.reverseBytes(in.readShort());
		chunk.sampleRate = Integer.reverseBytes(in.readInt());
		chunk.byteRate = Integer.reverseBytes(in.readInt());
		chunk.blockAlign =  Short.reverseBytes(in.readShort());
		chunk.bitsPerSample = Short.reverseBytes(in.readShort());
		if(chunk.code != 0){
			final short extraDataLen = Short.reverseBytes(in.readShort());			
			final byte extraData[] = new byte[extraDataLen];
			in.read(extraData);
			chunk.extraData = extraData;	
		}
		return chunk;
	}

	private final static WaveFactChunk readFactChunk(DataInputStream in) throws IOException{
		final int chunkSize = Integer.reverseBytes(in.readInt()) ;		
		final byte[] data = new byte[chunkSize];
		in.read(data);		
		return new WaveFactChunk( data);
	}
}
